# -*- coding: utf-8 -*-
# @Time    : 2024/8/13 16:43
# @Author  : LinChun
# @Email   : mLinChun@icloud.com
# @File    : core.py
# @Software: PyCharm

import nuke
import os
from pathlib import Path
import re
import shutil
from PySide2 import QtWidgets


def show_message():
    message = "bug/建议等请反馈到w&q:718422052或者邮箱:mLinChun@icloud.com"
    nuke.message(message)


def get_shuffle_in1_info(node):
   
    shuffle_node = node
    in1_knob = shuffle_node.knob('in1')
    current_value = in1_knob.value()
    return current_value



def repair_shuffle_name():
    shuffle_nodes = nuke.selectedNodes('Shuffle2')
    if shuffle_nodes:
        for node in shuffle_nodes:
            in1_value = get_shuffle_in1_info(node)
            in1_knob = node.knob('in1')
            # print(in1_value)
            channels = node.channels()
            modi_channels = set([item.split('.')[0] for item in channels])
            for channel in modi_channels:
                if in1_value.lower() == channel.lower():
                    # print(in1_value,channel)
                    in1_knob.setValue(channel)
                    break

    else: 
        nuke.message('请先选择节点再操作！')

def set_read_node_path(path):
    if path:
        pass
    else:
        path = nuke.getInput("请输入路径:")
    if path:
        # file_list = list_directories(path)
        # print(file_list)
        read_nodes = nuke.allNodes("Read")
        if read_nodes:
            for node in read_nodes:
                old_file = node['file'].value()
                old_name = old_file.split('/')[-2]+'/'+old_file.split('/')[-1]
                # print(old_name)
                new_file = os.path.join(path,old_name).replace('\\','/')
                # print(new_file)
                node["file"].setValue(new_file)
                node.knob("reload").execute()
                print(f"已替换 {old_file} 为 {new_file}")
        else:
            nuke.message("当前没有Read节点")
            return False
    else:
        nuke.message("未输入路径")
        return False

    return True


def find_latest_file(directory,geshi):

    # 获取所有.mov文件
    mov_files = list(Path(directory).glob('**/*.'+geshi))

    
    if not mov_files:
        return None
    
    # 按修改时间排序
    latest_by_mtime = max(mov_files, key=lambda x: x.stat().st_mtime)
    
    # 尝试按版本号排序
    try:
        # 提取文件名中的版本号（如v01, v001等）
        def extract_version(f):
            match = re.search(r'v(\d+)\.mov$', f.name, re.IGNORECASE)
            return int(match.group(1)) if match else 0
            
        latest_by_version = max(mov_files, key=extract_version)
        
        # 比较按修改时间和按版本号的结果
        if extract_version(latest_by_version) > extract_version(latest_by_mtime):
            return str(latest_by_version)
        return str(latest_by_mtime)
        
    except:
        # 如果版本号提取失败，返回按修改时间排序的结果
        return str(latest_by_mtime)

def sk_submit():
    base_sub_path = 'P:\\TVS048_SKBA_S1\\shots\\'
    if nuke.root().name() == "Root":
        nuke.message("项目尚未保存")

    else:
        file_path = nuke.root().name()
        proj_dir = os.path.dirname(file_path)
        file_name = os.path.basename(file_path)
        try:
            jishu = file_name.split('_')[0]
            changci = file_name.split('_')[1]
            jingtou = file_name.split('_')[2]
        except Exception as e:
            print(e)
            nuke.message("文件命名格式错误！")
            return None
        #nuke工程路径
        sub_nuk_path = base_sub_path + jishu + '\\' + changci + '\\' + jingtou + '\\EFXNUK\\'
        #序列路径
        sub_sqc_path = base_sub_path + jishu + '\\' + changci + '\\' + jingtou + '\\EFXSQC\\'
        #houdini工程路径
        sub_scn_path = base_sub_path + jishu + '\\' + changci + '\\' + jingtou + '\\EFXSCN\\'
        #mov路径
        sub_wqt_path = base_sub_path + jishu + '\\' + changci + '\\' + jingtou + '\\EFXQTM\\'
  
        if os.path.exists(sub_nuk_path):
            pass
        else:
            os.makedirs(sub_nuk_path)

        if os.path.exists(sub_scn_path):
            pass
        else:
            os.makedirs(sub_scn_path)

        if os.path.exists(sub_wqt_path):
            pass
        else:
            os.makedirs(sub_wqt_path)
    

        #mov文件
        wqt_file = find_latest_file(proj_dir,'mov')
        #nuke工程文件
        nuke_file = file_path
        #houdini工程文件
        scn_file = find_latest_file(proj_dir,'hip')
        #序列文件
        sqc_dir = proj_dir+"\\render\\"



        if os.path.exists(wqt_file):
            if os.path.exists(sqc_dir):
                pass
                
            else:
                nuke.message("没有找到render序列文件！")
                return None       
       
        else:
            nuke.message("没有找到mov文件！")
            return None


        
        nuke.message('即将开始复制文件...')

        try:
            shutil.copy(wqt_file,sub_wqt_path+os.path.basename(wqt_file))
        except Exception as e:
            print(e)
            nuke.message("复制mov文件失败！")
            return None

        try:
            shutil.copy(scn_file,sub_scn_path+os.path.basename(scn_file))
        except Exception as e:
            nuke.message("复制houdini文件失败！")
            return None

        try:
            if os.path.exists(sub_sqc_path):
                shutil.rmtree(sub_sqc_path) 
            shutil.copytree(sqc_dir, sub_sqc_path)  
        except Exception as e:
            print(e)
            nuke.message("复制序列文件失败！")
            return None

        finally:    
            if set_read_node_path(sub_sqc_path):
                nuke.scriptSaveAs(sub_nuk_path+file_name,1)
                nuke.message("提交成功！")


def multi_select_dialog(items, title="选择需要分层的通道"):
    app = QtWidgets.QApplication.instance()
    nuke_main_window = None
    for widget in app.topLevelWidgets():
        if widget.metaObject().className() == "Foundry::UI::DockMainWindow":
            nuke_main_window = widget
            break
    
    dialog = QtWidgets.QDialog(nuke_main_window)
    dialog.setWindowTitle(title)
    dialog.setMinimumSize(600, 400)
    

    layout = QtWidgets.QVBoxLayout(dialog)
    

    scroll = QtWidgets.QScrollArea()
    scroll.setWidgetResizable(True)
   
    content = QtWidgets.QWidget()
    scroll.setWidget(content)
    
    grid = QtWidgets.QGridLayout(content)
    grid.setSpacing(10)
    
    checkboxes = []
    for i, item in enumerate(items):
        cb = QtWidgets.QCheckBox(item)
        row = i // 3  # 3列布局
        col = i % 3
        grid.addWidget(cb, row, col)
        checkboxes.append(cb)
    
    # 按钮区域
    button_box = QtWidgets.QDialogButtonBox(
        QtWidgets.QDialogButtonBox.Ok | QtWidgets.QDialogButtonBox.Cancel
    )
    button_box.accepted.connect(dialog.accept)
    button_box.rejected.connect(dialog.reject)  # 修正了这里的拼写错误
    
    # 添加到主布局
    layout.addWidget(scroll)  # 修正了这里的变量名拼写
    layout.addWidget(button_box)
    
    # 显示对话框
    if dialog.exec_():
        return [items[i] for i, cb in enumerate(checkboxes) if cb.isChecked()]
    return []

def ql_shuff():
    nodes = nuke.selectedNodes()
    offset = 150;
    if nodes:
        for node in nodes:
            
            # print(node_posx,node_posy)
            channels = node.channels()
            node_posx = node.xpos()
            node_posy = node.ypos()
            print(channels)
            abschanels = []
            for channel in channels:
                abschanels.append(channel.split('.')[0])
            abschanels = list(set(abschanels))
            sels = multi_select_dialog(abschanels)
            i = 0
            for sel in sels:
                shuffle = nuke.createNode('Shuffle2')

                newpx = int(node_posx+i*offset)
                newpy = int(node_posy+offset)
                print(newpx,newpy)
                shuffle.setXpos(newpx)
                shuffle.setYpos(newpy)
                
                shuffle['in1'].setValue(sel)
                shuffle.setInput(0,node)
                i = i + 1

    else:
        nuke.message('请先选择节点')


def dzz_submit():
    base_sub_path = 'Y:\\shots\\'
    if nuke.root().name() == "Root":
        nuke.message("项目尚未保存")
    else:
        file_path = nuke.root().name()
        proj_dir = os.path.dirname(file_path)
        file_name = os.path.basename(file_path)
        try:
            jishu = file_name.split('_')[0]
            changci = file_name.split('_')[1]
            jingtou = file_name.split('_')[2]
        except Exception as e:
            print(e)
            nuke.message("文件命名格式错误！")
            return None
        #nuke工程路径
        sub_nuk_path = base_sub_path + jishu + '\\' + changci + '\\' + jingtou + '\\EFXNUK\\'
        #序列路径
        sub_sqc_path = base_sub_path + jishu + '\\' + changci + '\\' + jingtou + '\\EFXSQC\\'


        if not os.path.exists(sub_nuk_path):
            os.makedirs(sub_nuk_path)
        if not os.path.exists(sub_sqc_path):
            os.makedirs(sub_sqc_path)
            

        nuke_file = file_path
        sqc_dir = proj_dir+"\\render\\"

  
        nuke.message('即将开始复制文件...')

        try:
            if os.path.exists(sub_sqc_path):
                shutil.rmtree(sub_sqc_path) 
            shutil.copytree(sqc_dir, sub_sqc_path)  
        except Exception as e:
            print(e)
            nuke.message("复制序列文件失败！")
            return None

        finally:    
            if set_read_node_path(sub_sqc_path):
                nuke.scriptSaveAs(sub_nuk_path+file_name,1)
                nuke.message("提交成功！")


def set_read_relative_path():
    nuke.knob('root.project_directory', '[python {nuke.script_directory()}]')
    read_nodes = nuke.allNodes("Read")
    for node in read_nodes:
        file_path = node["file"].value()
        
        render_index = file_path.find("render")
        if render_index != -1:
            new_file_path = file_path[render_index:]
            node["file"].setValue(new_file_path)
        else:
            print("No 'render' keyword found in file path for node:", node.name())




def get_project_settings():
    """获取Nuke项目设置信息"""
    root = nuke.root()
    

    fps = root['fps'].value()
    start_frame = int(root['first_frame'].value())
    end_frame = int(root['last_frame'].value())


    format_node = root.format()
    width = format_node.width()
    height = format_node.height()
    pixel_aspect = format_node.pixelAspect()
    
    return {
        'fps': fps,
        'start_frame': start_frame,
        'end_frame': end_frame,
        'width': width,
        'height': height,
        'pixel_aspect': pixel_aspect,
        'format_name': format_node.name()
    }


def set_all_read_nodes_range():
    nuke_set = get_project_settings()
    try:
        start_frame = int(nuke_set['start_frame'])
        end_frame = int(nuke_set['end_frame'])
    except ValueError:
        nuke.message("错误：请输入有效的数字")
        return
    
    # 验证帧范围
    if start_frame > end_frame:
        nuke.message("错误：起始帧不能大于结束帧")
        return
    
    # 获取所有Read节点
    read_nodes = [node for node in nuke.allNodes() if node.Class() == "Read"]
    
    if not read_nodes:
        nuke.message("场景中没有Read节点")
        return
    
    # 修改所有Read节点的帧范围
    for read_node in read_nodes:
        read_node['first'].setValue(start_frame)
        read_node['last'].setValue(end_frame)
        read_node['origfirst'].setValue(start_frame)
        read_node['origlast'].setValue(end_frame)
    
    # 显示完成信息
    nuke.message("成功设置 {} 个Read节点的帧范围\n起始帧: {}\n结束帧: {}".format(
        len(read_nodes), start_frame, end_frame))


def copy_file_efficiently(source_path, destination_path):
    try:
        shutil.copy2(source_path, destination_path)
    except IOError as e:
        return False
    return True


def add_losed_frame():
    project_info = get_project_settings()
    start_frame = project_info['start_frame']
    end_frame = project_info['end_frame']
    width = project_info['width']
    height = project_info['height']
    exr_file = f"T:\\L_Tools\\Nuke\\blackexr\\{width}x{height}.exr"
    if not os.path.exists(exr_file):
        print(f"exr文件不存在{exr_file}")
        return
    
    read_nodes = [node for node in nuke.allNodes() if node.Class() == "Read"]
    if not read_nodes:
        nuke.message("场景中没有Read节点")
        return
    frame_list = [i for i in range(start_frame,end_frame+1)]
    

    print('开始处理缺失帧')
    for read_node in read_nodes:
        file_path = read_node['file'].value()
        for frame in frame_list:
            tmp_file = file_path.replace("%04d",f"{frame:04d}")
            if not os.path.exists(tmp_file):
                print(f"文件不存在{tmp_file}--开始复制")
                if copy_file_efficiently(exr_file,tmp_file):
                    print(f"文件复制成功: {exr_file} -> {tmp_file}".format(exr_file=exr_file, tmp_file=tmp_file))
        read_node['reload'].execute()
    nuke.message("添加缺失帧完成")




def ys_submit():
    base_sub_path = 'L:\\Project\\XCLTV_S1\\work\\Submit\\'
    if nuke.root().name() == "Root":
        nuke.message("项目尚未保存")

    else:
        file_path = nuke.root().name()
        proj_dir = os.path.dirname(file_path)
        file_name = os.path.splitext(os.path.basename(file_path))[0]
        try:
            jishu = file_name.split('_')[0]
            changci = file_name.split('_')[1]
            jingtou = file_name.split('_')[2]
        except Exception as e:
            print(e)
            nuke.message("文件命名格式错误！")
            return None
        #nuke工程路径
        sub_nuk_path = base_sub_path + jishu + '\\' + jishu + '_' + changci + '_' + jingtou + '\\image\\'
        #序列路径
        sub_sqc_path = base_sub_path + jishu + '\\' + jishu + '_' + changci + '_' + jingtou + '\\image\\render\\'
        #houdini工程路径
        sub_scn_path = base_sub_path + jishu + '\\' + jishu + '_' + changci + '_' + jingtou + '\\'
        #mov路径
        sub_wqt_path = base_sub_path + jishu + '\\' + jishu + '_' + changci + '_' + jingtou + '\\'
  
        if os.path.exists(sub_nuk_path):
            pass
        else:
            os.makedirs(sub_nuk_path)

        if os.path.exists(sub_scn_path):
            pass
        else:
            os.makedirs(sub_scn_path)

        if os.path.exists(sub_wqt_path):
            pass
        else:
            os.makedirs(sub_wqt_path)
    

        #mov文件
        wqt_file = find_latest_file(proj_dir,'mov')
   
        #houdini工程文件
        scn_file = find_latest_file(proj_dir,'hip')
        #序列文件
        sqc_dir = proj_dir+"\\render\\"



        if os.path.exists(wqt_file):
            if os.path.exists(sqc_dir):
                pass
                
            else:
                nuke.message("没有找到render序列文件！")
                return None       
       
        else:
            nuke.message("没有找到mov文件！")
            return None



        try:
            shutil.copy(wqt_file,sub_wqt_path+os.path.basename(wqt_file))
        except Exception as e:
            print(e)
            nuke.message("复制mov文件失败！")
            return None

        try:
            shutil.copy(scn_file,sub_scn_path+os.path.basename(scn_file))
        except Exception as e:
            nuke.message("复制houdini文件失败！")
            return None

        try:
            if os.path.exists(sub_sqc_path):
                shutil.rmtree(sub_sqc_path) 
            shutil.copytree(sqc_dir, sub_sqc_path)  
        except Exception as e:
            print(e)
            nuke.message("复制序列文件失败！")
            return None

        finally:    
            if set_read_node_path(sub_sqc_path):
                nuke.scriptSaveAs(sub_nuk_path+file_name+'.nk',1)
                set_read_relative_path()
                nuke.message("提交成功！")


def dp_submit():
    base_sub_path = '\\\\zx-nas\\Vfx\\V\\TVS054_DPCQ_NF4\\work\\Submit\\'
    if nuke.root().name() == "Root":
        nuke.message("项目尚未保存")
    else:
        file_path = nuke.root().name()
        proj_dir = os.path.dirname(file_path)
        file_name = os.path.basename(file_path)
        try:
            jishu = file_name.split('_')[0]
            changci = file_name.split('_')[1]
            jingtou = file_name.split('_')[2]
        except Exception as e:
            print(e)
            nuke.message("文件命名格式错误！")
            return None

        
        #nuke工程路径
        sub_nuk_path = base_sub_path + jishu + '_' + changci + '_' + jingtou + '\\work\\nuke\\'
        #houdini工程路径
        sub_scn_path = base_sub_path + jishu + '_' + changci + '_' + jingtou + '\\work\\houdini\\'
        #序列路径
        sub_sqc_path = base_sub_path + jishu + '_' + changci + '_' + jingtou + '\\work\\houdini\\render\\'
        #mov路径
        sub_wqt_path = base_sub_path + jishu + '_' + changci + '_' + jingtou + '\\video\\'
        #texture路径
        sub_tex_path = base_sub_path + jishu + '_' + changci + '_' + jingtou + '\\work\\houdini\\tex\\'





        if not os.path.exists(sub_nuk_path):
            os.makedirs(sub_nuk_path)
        if not os.path.exists(sub_sqc_path):
            os.makedirs(sub_sqc_path)
        if not os.path.exists(sub_wqt_path):
            os.makedirs(sub_wqt_path)
        if os.path.exists(sub_tex_path):
            shutil.rmtree(sub_tex_path)
        
        sqc_dir = proj_dir+"\\render\\"

  
        nuke.message('即将开始复制文件...')

        #mov文件
        wqt_file = find_latest_file(proj_dir,'mov')
        print(wqt_file)
        #houdini工程文件
        scn_file = find_latest_file(proj_dir,'hip')
        # print(scn_file)
        #texture文件
        tex_file = proj_dir+'\\tex\\'
        

        if os.path.exists(tex_file):
            try:
                shutil.copytree(tex_file,sub_tex_path)
            except Exception as e:
                print(e)
                nuke.message("复制texture文件失败！")
                return None
       
            
        try:
            shutil.copy(wqt_file,sub_wqt_path+os.path.basename(wqt_file))
        except Exception as e:
            print(e)
            nuke.message("复制mov文件失败！")
            return None

        try:
            shutil.copy(scn_file,sub_scn_path+os.path.basename(scn_file))
        except Exception as e:
            nuke.message("复制houdini文件失败！")
            return None

        try:
            if os.path.exists(sub_sqc_path):
                shutil.rmtree(sub_sqc_path) 
            shutil.copytree(sqc_dir, sub_sqc_path)  
        except Exception as e:
            print(e)
            nuke.message("复制序列文件失败！")
            return None

        finally:    
            if set_read_node_path(sub_sqc_path):
                nuke.scriptSaveAs(sub_nuk_path+file_name,1)
                set_read_node_path("../houdini/render")
                nuke.message("提交成功！")


if __name__ == '__main__':
    pass
